Bit Strings
題目
你的任務是算出長度為 的位元字串有多少個。
例如當 ,那答案就是 ,因為所有長度為 的位元字串分別是 000
、001
、010
、011
、100
、101
、110
、111
。
輸入
一個正整數 。()
輸出
輸出答案(長度 的位元字串數量)模 。
範例測資
Input :
3
Output :
8
想法:快速冪
字串中的每個字元都是 0
或 1
兩種二選一,所以 長度 的位元字串就總共有 種。那麼這題只要輸出 即可。
我們可以用俗稱「快速冪」的算法快速算出 ,這個算法只有 的時間複雜度,比起 的直接連乘法快上許多。
考慮一個滿足結合律的「乘法」運算 ,並且把 個 「乘」在一起用 表示。因為「乘法」滿足結合律,所以「次方」也會滿足指數律: 快速冪的核心概念就是用指數律來降低「乘法」的次數。我們通常會用 來除,比如說把 變成 或 。像這樣一直遞迴下去,我們就能用 次的「乘法」算出 。
注意到我們有以下的事實: 如果我們進一步把 定義成 ,我們還可以驗證說這個運算的確滿足結合律。所以我們可以直接把取模寫進快速冪裡面,而不用整個算完再取模。(而且如果整個算完,數字可能會大到存不下)
因為快速冪有不少種寫法,下面的範例程式碼先省略不定義 fastpow
,後面再把幾種寫法列出來。
範例程式碼
C++ 範例
#include <iostream>
using namespace std;
int MOD = 1000000007;
int fastpow(int x, int n);
int main() {
int n;
cin >> n;
cout << fastpow(2, n);
}
快速冪 1:
例如 。
這裡使用以下的規則: 並使用遞迴來實現。
如果沒有「乘法」單位元素 ,要把初始條件改成 時回傳 。
C++ 範例
int fastpow(int x, int n) {
if (n == 0)
return 1;
int u = fastpow(x, n/2);
u = (u * u) % MOD;
if (n % 2)
u = (u * x) % MOD;
return u;
}
快速冪 2:
例如 ,其中 都是從已經算過的 「平方」之後算出來的。
這裡使用以下的規則: 並使用遞迴來實現。
如果沒有「乘法」單位元素 ,要把初始條件改成 時回傳 。
C++ 範例
int fastpow(int x, int n) {
if (n == 0)
return 1;
int u = fastpow((x * x) % MOD, n/2);
if (n % 2)
u = (u * x) % MOD;
return u;
}
我們也可以寫成迴圈。這個順序恰好跟遞迴版本顛倒,以 為例,上面的遞迴版會算 ,而下面的迴圈版是算 。
C++ 範例
int fastpow(int x, int n) {
int r = 1;
while (n) {
if (n % 2)
r = (r * x) % MOD;
x = (x * x) % MOD;
n /= 2;
}
return u;
}